home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsio / fsioPipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  34.9 KB  |  1,213 lines

  1. /*
  2.  * fsPipe.c --
  3.  *
  4.  *    Routines for unnamed pipes.  An unnamed pipe has a fixed length
  5.  *    resident buffer, a reading stream, and a writing stream.
  6.  *    Process migration can result in remotely accessed pipes.
  7.  *
  8.  * Copyright (C) 1985 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsio/fsioPipe.c,v 9.12 92/08/10 17:26:55 mgbaker Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16.  
  17. #include <sprite.h>
  18.  
  19. #include <fs.h>
  20. #include <fsutil.h>
  21. #include <fsio.h>
  22. #include <fsNameOps.h>
  23. #include <fsconsist.h>
  24. #include <fsStat.h>
  25. #include <fsrmt.h>
  26. #include <vm.h>
  27. #include <proc.h>
  28. #include <rpc.h>
  29. #include <fsioPipe.h>
  30.  
  31. #include <stdio.h>
  32. #include <recov.h>
  33.  
  34. /*
  35.  * Monitor to synchronize access to the openInstance in GetFileID.
  36.  */
  37. static    Sync_Lock    pipeLock = Sync_LockInitStatic("Fs:pipeLock");
  38. #define    LOCKPTR    &pipeLock
  39.  
  40. /*
  41.  * Forward references.
  42.  */
  43. static void GetFileID _ARGS_((Fs_FileID *fileIDPtr));
  44. extern Fsio_PipeIOHandle *Fsio_PipeHandleInit _ARGS_((Fs_FileID *fileIDPtr, 
  45.         Boolean findIt));
  46. static ReturnStatus PipeCloseInt _ARGS_((Fsio_PipeIOHandle *handlePtr, 
  47.         int ref, int write, Boolean release));
  48.  
  49. /*
  50.  * Migration debugging.
  51.  */
  52. #ifdef MIG_DEBUG
  53.  
  54. #define PIPE_CREATED(inStreamPtr, outStreamPtr) \
  55.     { \
  56.     printf("Create Pipe: Srvr %d Read <%d> Write <%d> I/O %d <%d,%d>\n", \
  57.         (inStreamPtr)->hdr.fileID.serverID, \
  58.         (inStreamPtr)->hdr.fileID.minor, \
  59.         (outStreamPtr)->hdr.fileID.minor, \
  60.         (inStreamPtr)->ioHandlePtr->fileID.serverID, \
  61.         (inStreamPtr)->ioHandlePtr->fileID.major, \
  62.         (inStreamPtr)->ioHandlePtr->fileID.minor); \
  63.     }
  64.  
  65. #define PIPE_CLOSE(streamPtr, handlePtr) \
  66.     printf("Pipe Close: Stream %s <%d> I/O <%d,%d> ref %d write %d flags %x\n", \
  67.         ((streamPtr)->flags & FS_READ) ? "Read" : "Write", \
  68.         (streamPtr)->hdr.fileID.minor, \
  69.         (handlePtr)->hdr.fileID.major, (handlePtr)->hdr.fileID.minor, \
  70.         (handlePtr)->use.ref, (handlePtr)->use.write, \
  71.         (handlePtr)->flags)
  72.  
  73. #define PIPE_MIG_1(migInfoPtr, dstClientID) \
  74.     printf("Pipe Migrate: %d => %d Stream %d <%d> I/O <%d,%d> migFlags %x ", \
  75.         (migInfoPtr)->srcClientID, dstClientID, \
  76.         (migInfoPtr)->streamID.serverID, (migInfoPtr)->streamID.minor, \
  77.         (migInfoPtr)->ioFileID.major, (migInfoPtr)->ioFileID.minor, \
  78.         (migInfoPtr)->flags);
  79.  
  80. #define PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr) \
  81.     printf("=> %x\n    closeSrc %d (ref %d write %d", (migInfoPtr)->flags, \
  82.         closeSrcClient, (handlePtr)->use.ref, (handlePtr)->use.write);
  83.  
  84. #define PIPE_MIG_3(handlePtr) \
  85.     printf(" | ref %d write %d)\n", \
  86.         (handlePtr)->use.ref, (handlePtr)->use.write);
  87.  
  88. #define PIPE_MIG_END(handlePtr) \
  89.     printf("PipeMigEnd: I/O <%d,%d> ref %d write %d\n", \
  90.         (handlePtr)->hdr.fileID.major, (handlePtr)->hdr.fileID.minor, \
  91.         (handlePtr)->use.ref, (handlePtr)->use.write)
  92. #else
  93.  
  94. #define PIPE_CREATED(inStreamPtr, outStreamPtr)
  95. #define PIPE_CLOSE(streamPtr, handlePtr)
  96. #define PIPE_MIG_1(migInfoPtr, dstClientID)
  97. #define PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr)
  98. #define PIPE_MIG_3(handlePtr)
  99. #define PIPE_MIG_END(handlePtr)
  100.  
  101. #endif /* MIG_DEBUG */
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  *
  106.  * Fsio_CreatePipe --
  107.  *
  108.  *      Create an unnamed pipe.  Pointers to streams for both ends of the pipe
  109.  *    are returned in *inStreamPtrPtr and *outStreamPtrPtr.
  110.  *
  111.  * Results:
  112.  *    SUCCESS.
  113.  *
  114.  * Side effects:
  115.  *    None.
  116.  *
  117.  *----------------------------------------------------------------------
  118.  */
  119.  
  120. ReturnStatus
  121. Fsio_CreatePipe(inStreamPtrPtr, outStreamPtrPtr)
  122.     Fs_Stream **inStreamPtrPtr;        /* Return - in (reading) stream */
  123.     Fs_Stream **outStreamPtrPtr;    /* Return - out (writing) stream */
  124. {
  125.     Fs_FileID        fileID;
  126.     register Fsio_PipeIOHandle    *handlePtr;
  127.     register Fs_Stream        *streamPtr;
  128.  
  129.     /*
  130.      * Set up the I/O handle for the pipe.  The installation puts
  131.      * one reference on the I/O handle.
  132.      */
  133.  
  134.     GetFileID(&fileID);
  135.     handlePtr = Fsio_PipeHandleInit(&fileID, FALSE);
  136.     (void)Fsconsist_IOClientOpen(&handlePtr->clientList, rpc_SpriteID, FS_READ, FALSE);
  137.     (void)Fsconsist_IOClientOpen(&handlePtr->clientList, rpc_SpriteID, FS_WRITE, FALSE);
  138.  
  139.     /*
  140.      * Allocate and initialize the read, or "in", end of the stream.
  141.      */
  142.     streamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  143.                 (Fs_HandleHeader *)handlePtr,
  144.                 FS_READ | FS_USER, "read-pipe");
  145.     Fsutil_HandleUnlock(streamPtr);
  146.     *inStreamPtrPtr = streamPtr;
  147.  
  148.     /*
  149.      * Set up the writing end.  Note that we get a second reference to
  150.      * the I/O handle by duping it.
  151.      */
  152.     Fsutil_HandleUnlock(handlePtr);
  153.     (void)Fsutil_HandleDup((Fs_HandleHeader *)handlePtr);
  154.     streamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  155.             (Fs_HandleHeader *)handlePtr,
  156.             FS_WRITE | FS_APPEND | FS_USER, "write-pipe");
  157.     Fsutil_HandleUnlock(handlePtr);
  158.     Fsutil_HandleUnlock(streamPtr);
  159.     *outStreamPtrPtr = streamPtr;
  160.  
  161.     PIPE_CREATED(*inStreamPtrPtr, *outStreamPtrPtr);
  162.  
  163.     return(SUCCESS);
  164. }
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * GetFileID --
  170.  *
  171.  *      Get a unique file ID for the pipe.  This is a monitor to synchronize
  172.  *    access to the openInstance variable that gives us unique file
  173.  *    ids for unnamed pipes.
  174.  *
  175.  * Results:
  176.  *    Unique file ID.
  177.  *
  178.  * Side effects:
  179.  *    Open instance incremented.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183.  
  184. static ENTRY void
  185. GetFileID(fileIDPtr)
  186.     Fs_FileID    *fileIDPtr;
  187. {
  188.     static int openInstance = 0;
  189.  
  190.     LOCK_MONITOR;
  191.  
  192.     fileIDPtr->type = FSIO_LCL_PIPE_STREAM;
  193.     fileIDPtr->serverID = rpc_SpriteID;
  194.     fileIDPtr->major = 0;
  195.     fileIDPtr->minor = openInstance;
  196.     openInstance++;
  197.  
  198.     UNLOCK_MONITOR;
  199. }
  200.  
  201. /*
  202.  *----------------------------------------------------------------------
  203.  *
  204.  * Fsio_PipeHandleInit --
  205.  *
  206.  *    Initialize a handle for a pipe.
  207.  *
  208.  * Results:
  209.  *    A pointer to the pipe handle.
  210.  *
  211.  * Side effects:
  212.  *    Create and install a handle for the file.  It is returned locked
  213.  *    and with its reference count incremented if SUCCESS is returned.
  214.  *
  215.  *----------------------------------------------------------------------
  216.  */
  217. Fsio_PipeIOHandle *
  218. Fsio_PipeHandleInit(fileIDPtr, findIt)
  219.     Fs_FileID    *fileIDPtr;    /* Pipe file ID */
  220.     Boolean    findIt;        /* TRUE if we expect to find its handle */
  221. {
  222.     Fs_HandleHeader *hdrPtr;
  223.     register Fsio_PipeIOHandle *handlePtr;
  224.     register Boolean found;
  225.  
  226.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsio_PipeIOHandle), "pipe",
  227.         FALSE, &hdrPtr);
  228.     handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  229.     if (!found) {
  230.     if (findIt) {
  231.         panic( "Fsio_PipeHandleInit, didn't find handle\n");
  232.     }
  233.     /*
  234.      * When a pipe is created, it has one read and one write
  235.      * reference on the handle.
  236.      */
  237.     handlePtr->use.ref = 2;
  238.     handlePtr->use.write = 1;
  239.     handlePtr->use.exec = 0;
  240.     List_Init(&handlePtr->clientList);
  241.     handlePtr->flags = 0;
  242.     handlePtr->firstByte = handlePtr->lastByte = -1;
  243.     handlePtr->buffer = (Address)malloc(FS_BLOCK_SIZE);
  244.     handlePtr->bufSize = FS_BLOCK_SIZE;
  245.     List_Init(&handlePtr->readWaitList);
  246.     List_Init(&handlePtr->writeWaitList);
  247.     fs_Stats.object.pipes++;
  248.     }
  249.     return(handlePtr);
  250. }
  251.  
  252. /*
  253.  *----------------------------------------------------------------------
  254.  *
  255.  * Fsio_PipeClose --
  256.  *
  257.  *      Close a local pipe.  Other processes waiting on the pipe are
  258.  *    unblocked and the pipe's buffer is freed when the last
  259.  *    user goes away.
  260.  *
  261.  * Results:
  262.  *      SUCCESS.
  263.  *
  264.  * Side effects:
  265.  *      Unblock local waiting reader (or writer) waiting on the pipe.
  266.  *
  267.  *----------------------------------------------------------------------
  268.  */
  269. /*ARGSUSED*/
  270. ReturnStatus
  271. Fsio_PipeClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  272.     Fs_Stream        *streamPtr;    /* Stream to a pipe */
  273.     int            clientID;    /* Host ID of closing process */
  274.     Proc_PID        procID;        /* Process closing */
  275.     int            flags;        /* Flags from the stream being closed */
  276.     int            dataSize;    /* Should be 0 */
  277.     ClientData        closeData;    /* Should be NIL */
  278. {
  279.     register Fsio_PipeIOHandle *handlePtr = 
  280.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  281.     Boolean cache = FALSE;
  282.     ReturnStatus status;
  283.  
  284.     if (!Fsconsist_IOClientClose(&handlePtr->clientList, clientID, flags, &cache)) {
  285.     printf( "Fsio_PipeClose, unknown client %d\n", clientID);
  286.     Fsutil_HandleUnlock(handlePtr);
  287.     } else {
  288.     PIPE_CLOSE(streamPtr, handlePtr);
  289.     status = PipeCloseInt(handlePtr, 1, (flags & FS_WRITE) != 0, TRUE);
  290.     if (status != FS_FILE_REMOVED) {
  291.         Fsutil_HandleRelease(handlePtr, TRUE);
  292.     }
  293.     }
  294.     return(SUCCESS);
  295. }
  296.  
  297. /*
  298.  *----------------------------------------------------------------------
  299.  *
  300.  * PipeCloseInt --
  301.  *
  302.  *      Do the real work of closing a pipe, given a variable number
  303.  *    of references. 
  304.  *
  305.  * Results:
  306.  *      SUCCESS or FS_FILE_REMOVED, which indicates that the pipe has been
  307.  *     freed up.
  308.  *
  309.  * Side effects:
  310.  *      Unblock local waiting reader (or writer) waiting on the pipe.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314. /*ARGSUSED*/
  315. static ReturnStatus
  316. PipeCloseInt(handlePtr, ref, write, release)
  317.     Fsio_PipeIOHandle *handlePtr;    /* Pipe to clean up */
  318.     int ref;                /* Number of uses to remove */
  319.     int write;                /* Number of writers to remove */
  320.     Boolean release;            /* Whether to release handle to
  321.                        remove it. */
  322. {
  323.     /*
  324.      * Update the global/summary use counts for the file.
  325.      */
  326.     handlePtr->use.ref -= ref;
  327.     handlePtr->use.write -= write;
  328.     if (handlePtr->use.ref < 0 || handlePtr->use.write < 0) {
  329.     panic("PipeCloseInt <%d,%d> use %d, write %d\n",
  330.           handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor,
  331.           handlePtr->use.ref, handlePtr->use.write);
  332.     }
  333.     if (write && handlePtr->use.write == 0) {
  334.     /*
  335.      * Notify reader that the writer has closed.
  336.      */
  337.     handlePtr->flags |= FSIO_PIPE_WRITER_GONE;
  338.     Fsutil_FastWaitListNotify(&handlePtr->readWaitList);
  339.     } else if (ref && handlePtr->use.ref == handlePtr->use.write) {
  340.     /*
  341.      * Update state and notify any blocked writers.  Their write
  342.      * will fail with no remaining readers.
  343.      */
  344.     handlePtr->flags |= FSIO_PIPE_READER_GONE;
  345.     Fsutil_FastWaitListNotify(&handlePtr->writeWaitList);
  346.     }
  347.     if (handlePtr->flags == (FSIO_PIPE_WRITER_GONE|FSIO_PIPE_READER_GONE)) {
  348.     free(handlePtr->buffer);
  349.     Fsutil_WaitListDelete(&handlePtr->readWaitList);
  350.     Fsutil_WaitListDelete(&handlePtr->writeWaitList);
  351.     if (release) {
  352.         Fsutil_HandleRelease(handlePtr, FALSE);
  353.     }
  354.     Fsutil_HandleRemove(handlePtr);
  355.     fs_Stats.object.pipes--;
  356.     return (FS_FILE_REMOVED);
  357.     }
  358.     /*
  359.      * Handle will be released or unlocked by caller as appropriate.
  360.      */
  361.     return(SUCCESS);
  362. }
  363.  
  364. /*
  365.  *----------------------------------------------------------------------
  366.  *
  367.  * Fsio_PipeRead --
  368.  *
  369.  *      Read on a pipe.  Data is copied out of the pipe to satisfy the
  370.  *    read.  If the pipe is empty this routine returns FS_WOULD_BLOCK.
  371.  *    If the pipe writer is gone this returns SUCCESS and 0 bytes
  372.  *    to simulate EOF.
  373.  *
  374.  * Results:
  375.  *      SUCCESS unless there was an address error or I/O error.
  376.  *
  377.  * Side effects:
  378.  *      Fill in the buffer.  Notifies the pipe's writeWaitList after
  379.  *    removing data from the pipe.
  380.  *
  381.  *----------------------------------------------------------------------
  382.  */
  383. /*ARGSUSED*/
  384. ReturnStatus
  385. Fsio_PipeRead(streamPtr, readPtr, waitPtr, replyPtr)
  386.     Fs_Stream           *streamPtr;     /* Stream to read from */
  387.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  388.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  389.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  390.                      * plus the amount read. */
  391. {
  392.     ReturnStatus     status = SUCCESS;
  393.     register Fsio_PipeIOHandle *handlePtr =
  394.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  395.     int         toRead;
  396.     int         startOffset;
  397.     int            startByte;
  398.     int            endByte;
  399.  
  400.     Fsutil_HandleLock(handlePtr);
  401.  
  402.     if (handlePtr->firstByte == -1) {
  403.     /*
  404.      * No data in the pipe.  If there is no writer left then
  405.      * return SUCCESS so the user process thinks of it as end of file,
  406.      * otherwise block waiting for input.
  407.      */
  408.     replyPtr->length = 0;
  409.     if (handlePtr->flags & FSIO_PIPE_WRITER_GONE) {
  410.         status = SUCCESS;
  411.         goto exit;
  412.     } else {
  413.         status = FS_WOULD_BLOCK;
  414.         goto exit;
  415.     }
  416.     }
  417.     /*
  418.      * Compute the number of bytes that we can read from the pipe.  
  419.      */
  420.     toRead = handlePtr->lastByte - handlePtr->firstByte + 1;
  421.     if (toRead > readPtr->length) {
  422.     toRead = readPtr->length;
  423.     }
  424.  
  425.     /*
  426.      * Compute offsets into the pipe buffer.  The offsets float out past
  427.      * the size of the buffer, but we use masks to take of the top bits.
  428.      * We can also compare these top bits to determine if the valid range
  429.      * of the buffer wraps around the end of the pipe.
  430.      */
  431.     startByte = handlePtr->firstByte;
  432.     startOffset = startByte & FS_BLOCK_OFFSET_MASK;
  433.     endByte = handlePtr->firstByte + toRead - 1;
  434.  
  435.     if ((startByte & ~FS_BLOCK_OFFSET_MASK) ==
  436.     (endByte & ~FS_BLOCK_OFFSET_MASK)) {
  437.     /*
  438.      * Can do a straight copy, no wrap around necessary.
  439.      */
  440.     if (readPtr->flags & FS_USER) {
  441.         if (Vm_CopyOut(toRead, handlePtr->buffer + startOffset, readPtr->buffer)
  442.               != SUCCESS) {
  443.         status = SYS_ARG_NOACCESS;
  444.         }
  445.     } else {
  446.         bcopy(handlePtr->buffer + startOffset, readPtr->buffer, toRead);
  447.     }
  448.     } else {
  449.     int    numBytes;
  450.     /*
  451.      * Have to wrap around in the block so do it in two copies.
  452.      */
  453.     numBytes = FS_BLOCK_SIZE - startOffset;
  454.     if (readPtr->flags & FS_USER) {
  455.         if (Vm_CopyOut(numBytes, handlePtr->buffer + startOffset, readPtr->buffer)
  456.               != SUCCESS) {
  457.         status = SYS_ARG_NOACCESS;
  458.         } else if (Vm_CopyOut(toRead - numBytes, handlePtr->buffer,
  459.                 readPtr->buffer + numBytes) != SUCCESS) {
  460.         status = SYS_ARG_NOACCESS;
  461.         }
  462.     } else {
  463.         bcopy(handlePtr->buffer + startOffset, readPtr->buffer, numBytes);
  464.         bcopy(handlePtr->buffer, readPtr->buffer + numBytes, toRead - numBytes);
  465.     }
  466.     }
  467.  
  468.     /*
  469.      * We just made space in the pipe so wake up blocked writers.
  470.      */
  471.     Fsutil_FastWaitListNotify(&handlePtr->writeWaitList);
  472.  
  473.     /*
  474.      * Update the first byte and the parameters.
  475.      */
  476.     handlePtr->firstByte += toRead;
  477.     if (handlePtr->firstByte > handlePtr->lastByte) {
  478.     handlePtr->firstByte = -1;
  479.     handlePtr->lastByte = -1;
  480.     }
  481.     replyPtr->length = toRead;
  482. exit:
  483.     if (status == FS_WOULD_BLOCK) {
  484.     Fsutil_FastWaitListInsert(&handlePtr->readWaitList, waitPtr);
  485.     }
  486.     Fsutil_HandleUnlock(handlePtr);
  487.     return(status);
  488. }
  489.  
  490.  
  491. /*
  492.  *----------------------------------------------------------------------
  493.  *
  494.  * Fsio_PipeWrite --
  495.  *
  496.  *      Write on a pipe.  This will put as much data as possible into the
  497.  *    pipe buffer, and then block the process (return would-block) if
  498.  *    there is any left over data.  *lenPtr is updated to reflect how
  499.  *    much data was written to the pipe.
  500.  *
  501.  * Results:
  502.  *      SUCCESS unless there was an address error or I/O error.
  503.  *
  504.  * Side effects:
  505.  *      Fill the pipe from the buffer.
  506.  *
  507.  *----------------------------------------------------------------------
  508.  */
  509. ReturnStatus
  510. Fsio_PipeWrite(streamPtr, writePtr, waitPtr, replyPtr)
  511.     Fs_Stream           *streamPtr;     /* Stream to write to */
  512.     Fs_IOParam        *writePtr;    /* Read parameter block */
  513.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  514.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  515. {
  516.     register ReturnStatus     status = SUCCESS;
  517.     register Fsio_PipeIOHandle    *handlePtr =
  518.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  519.     int             startOffset;
  520.     register int         toWrite;
  521.     int                startByte;
  522.     int                endByte;
  523.  
  524.     Fsutil_HandleLock(handlePtr);
  525.  
  526.     if (handlePtr->flags & FSIO_PIPE_READER_GONE) {
  527.     replyPtr->length = 0;
  528.     replyPtr->signal = SIG_PIPE;
  529.     status = FS_BROKEN_PIPE;
  530.     goto exit;
  531.     }
  532.  
  533.     /*
  534.      * Compute the number of bytes that will fit in the pipe.  Remember
  535.      * that the pipe can only hold one block of data.
  536.      */
  537.     if (handlePtr->firstByte == -1) {
  538.     toWrite = FS_BLOCK_SIZE;
  539.     } else {
  540.     toWrite = FS_BLOCK_SIZE - 
  541.             (handlePtr->lastByte - handlePtr->firstByte + 1);
  542.     }
  543.     if (toWrite == 0) {
  544.     /*
  545.      * No room in the pipe.
  546.      */
  547.     replyPtr->length = 0;
  548.     status = FS_WOULD_BLOCK;
  549.     goto exit;
  550.     } else if (toWrite > writePtr->length) {
  551.     toWrite = writePtr->length;
  552.     } else if (writePtr->length > toWrite) {
  553.     /*
  554.      * If there is more data to write we must block after writing the
  555.      * data that we can.  
  556.      */
  557.     status = FS_WOULD_BLOCK;
  558.     }
  559.     /*
  560.      * Determine where to start and stop writing.  Note that the firstByte
  561.      * and lastByte offsets float out beyond the size of the pipe but
  562.      * we use masks to clear off the extra high order bits.
  563.      */
  564.     startByte = handlePtr->lastByte + 1;
  565.     startOffset = startByte & FS_BLOCK_OFFSET_MASK;
  566.     endByte = handlePtr->lastByte + toWrite;
  567.  
  568.     if ((startByte & ~FS_BLOCK_OFFSET_MASK) ==
  569.     (endByte & ~FS_BLOCK_OFFSET_MASK)) {
  570.     /*
  571.      * Can do a straight copy, no wrap around necessary.
  572.      */
  573.     if (writePtr->flags & FS_USER) {
  574.         if (Vm_CopyIn(toWrite, writePtr->buffer, handlePtr->buffer + startOffset)
  575.               != SUCCESS) {
  576.         status = SYS_ARG_NOACCESS;
  577.         }
  578.     } else {
  579.         bcopy(writePtr->buffer, handlePtr->buffer + startOffset, toWrite);
  580.     }
  581.     } else {
  582.     int    numBytes;
  583.     /*
  584.      * Have to wrap around in the block so do it in two copies.
  585.      */
  586.     numBytes = FS_BLOCK_SIZE - startOffset;
  587.     if (writePtr->flags & FS_USER) {
  588.         if (Vm_CopyIn(numBytes, writePtr->buffer, handlePtr->buffer + startOffset)
  589.               != SUCCESS) {
  590.         status = SYS_ARG_NOACCESS;
  591.         } else if (Vm_CopyIn(toWrite - numBytes, writePtr->buffer + numBytes, 
  592.                 handlePtr->buffer) != SUCCESS) {
  593.         status = SYS_ARG_NOACCESS;
  594.         }
  595.     } else {
  596.         bcopy(writePtr->buffer, handlePtr->buffer + startOffset, numBytes);
  597.         bcopy(writePtr->buffer + numBytes, handlePtr->buffer, toWrite - numBytes);
  598.     }
  599.     }
  600.  
  601.     /*
  602.      * We just wrote to the pipe so wake up blocked readers.
  603.      */
  604.     Fsutil_FastWaitListNotify(&handlePtr->readWaitList);
  605.  
  606.     /*
  607.      * Update first byte, last byte and the parameters.
  608.      */
  609.     if (handlePtr->firstByte == -1) {
  610.     handlePtr->firstByte = 0;
  611.     }
  612.     handlePtr->lastByte = endByte;
  613.     replyPtr->length = toWrite;
  614. exit:
  615.     if (status == FS_WOULD_BLOCK) {
  616.     Fsutil_FastWaitListInsert(&handlePtr->writeWaitList, waitPtr);
  617.     }
  618.     Fsutil_HandleUnlock(handlePtr);
  619.     return(status);
  620. }
  621.  
  622.  
  623. /*
  624.  *----------------------------------------------------------------------
  625.  *
  626.  * Fsio_PipeIOControl --
  627.  *
  628.  *    Check the IOC_CLEAR_FLAG control, and allow the IOC_SET_FLAG control.
  629.  *
  630.  * Results:
  631.  *      SUCCESS unless they try to clear the FS_APPEND flag.
  632.  *
  633.  * Side effects:
  634.  *      None.
  635.  *
  636.  *----------------------------------------------------------------------
  637.  */
  638. /*ARGSUSED*/
  639. ReturnStatus
  640. Fsio_PipeIOControl(streamPtr, ioctlPtr, replyPtr)
  641.     Fs_Stream *streamPtr;
  642.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  643.     Fs_IOReply *replyPtr;        /* Return length and signal */
  644. {
  645.     register Fsio_PipeIOHandle *handlePtr =
  646.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  647.     register int command = ioctlPtr->command;
  648.     ReturnStatus status = SUCCESS;
  649.  
  650.     switch(command) {
  651.     case IOC_REPOSITION:
  652.         return(FS_BAD_SEEK);
  653.     case IOC_GET_FLAGS:
  654.     case IOC_SET_BITS:
  655.         return(SUCCESS);
  656.     case IOC_CLEAR_BITS:
  657.     case IOC_SET_FLAGS: {
  658.         /*
  659.          * Guard against turning off append mode in pipes.
  660.          */
  661.         int flags;
  662.         int size;
  663.         int inSize;
  664.  
  665.         if (ioctlPtr->inBufSize != sizeof(int)) {
  666.         status = GEN_INVALID_ARG;
  667.         } else if (ioctlPtr->format != mach_Format) {
  668.         int fmtStatus;
  669.         size = sizeof(int);
  670.         inSize = ioctlPtr->inBufSize;
  671.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  672.                 ioctlPtr->inBuffer, mach_Format, &size,
  673.                 (Address) &flags);
  674.         if (fmtStatus != 0) {
  675.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  676.             status = GEN_INVALID_ARG;
  677.         }
  678.         if (size != sizeof(int)) {
  679.             status = GEN_INVALID_ARG;
  680.         }
  681.         } else {
  682.         flags = *(int *)ioctlPtr->inBuffer;
  683.         }
  684.         if (status != SUCCESS) {
  685.         return(status);
  686.         }
  687.         if ((command == IOC_SET_FLAGS && (flags & IOC_APPEND) == 0) ||
  688.         (command == IOC_CLEAR_BITS && (flags & IOC_APPEND))) {
  689.         return(GEN_INVALID_ARG);
  690.         }
  691.         return(SUCCESS);
  692.     }
  693.     case IOC_TRUNCATE:
  694.     case IOC_LOCK:
  695.     case IOC_UNLOCK:
  696.         return(GEN_NOT_IMPLEMENTED);
  697.     case IOC_NUM_READABLE: {
  698.         int bytesAvailable = handlePtr->lastByte - handlePtr->firstByte;
  699.  
  700.         if (ioctlPtr->outBufSize != sizeof(int)) {
  701.         status = GEN_INVALID_ARG;
  702.         } else if (ioctlPtr->format != mach_Format) {
  703.         int size = sizeof(int);
  704.         int inSize = sizeof(int);
  705.         int fmtStatus;
  706.         fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  707.                 (Address) &bytesAvailable, ioctlPtr->format, 
  708.                 &size, (Address) ioctlPtr->outBuffer);
  709.         if (fmtStatus != 0) {
  710.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  711.             status = GEN_INVALID_ARG;
  712.         }
  713.         if (size != sizeof(int)) {
  714.             status = GEN_INVALID_ARG;
  715.         }
  716.         } else {
  717.         *(int *)ioctlPtr->outBuffer = bytesAvailable;
  718.         }
  719.         return(status);
  720.     }
  721.     case IOC_GET_OWNER:
  722.     case IOC_SET_OWNER:
  723.     case IOC_MAP:
  724.     case IOC_PREFIX:
  725.         return(GEN_NOT_IMPLEMENTED);
  726.     default:
  727.         return(GEN_INVALID_ARG);
  728.     }
  729. }
  730.  
  731. /*
  732.  *----------------------------------------------------------------------
  733.  *
  734.  * Fsio_PipeSelect --
  735.  *
  736.  *    Select on a pipe.
  737.  *
  738.  * Results:
  739.  *      SUCCESS unless there was an address error or I/O error.
  740.  *
  741.  * Side effects:
  742.  *      Fill the pipe from the buffer.
  743.  *
  744.  *----------------------------------------------------------------------
  745.  */
  746. ReturnStatus
  747. Fsio_PipeSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  748.     Fs_HandleHeader *hdrPtr;    /* The handle of the file */
  749.     Sync_RemoteWaiter *waitPtr;    /* Process info for waiting */
  750.     int        *readPtr;    /* Read bit */
  751.     int        *writePtr;    /* Write bit */
  752.     int        *exceptPtr;    /* Exception bit */
  753. {
  754.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  755.  
  756.     Fsutil_HandleLock(hdrPtr);
  757.     *exceptPtr = 0;
  758.     if (*writePtr) {
  759.     /*
  760.      * Turn off writability if the pipe is full and there
  761.      * are still readers.  If there are no readers we allow
  762.      * writing but the next write will fail.
  763.      */
  764.     if ((((handlePtr->firstByte + 1) % FS_BLOCK_SIZE) ==
  765.          handlePtr->lastByte) && 
  766.          ((handlePtr->flags & FSIO_PIPE_READER_GONE) == 0)) {
  767.         if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  768.         Fsutil_FastWaitListInsert(&handlePtr->writeWaitList, waitPtr);
  769.         }
  770.         *writePtr = 0;
  771.     }
  772.     }
  773.     if (*readPtr) {
  774.     /*
  775.      * If there's data to be read then set the READABLE bit.
  776.      * If all the writers have died, then this process will never be 
  777.      * woken up again so lie and say the pipe is readble. The process
  778.      * discover there's no writer when it tries to read the pipe.
  779.      */
  780.     if ((handlePtr->firstByte == -1) &&
  781.         ((handlePtr->flags & FSIO_PIPE_WRITER_GONE) == 0)) {
  782.         *readPtr = 0;
  783.         if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  784.         Fsutil_FastWaitListInsert(&handlePtr->readWaitList, waitPtr);
  785.         }
  786.         }
  787.     }
  788.     Fsutil_HandleUnlock(hdrPtr);
  789.     return(SUCCESS);
  790. }
  791.  
  792. /*
  793.  *----------------------------------------------------------------------
  794.  *
  795.  * Fsio_PipeGetIOAttr --
  796.  *
  797.  *    Get the most up-to-date I/O attributes for a pipe.
  798.  *
  799.  * Results:
  800.  *    SUCCESS
  801.  *
  802.  * Side effects:
  803.  *      Updates the first and last byte indexes of the handle.
  804.  *
  805.  *----------------------------------------------------------------------
  806.  */
  807. /*ARGSUSED*/
  808. ReturnStatus
  809. Fsio_PipeGetIOAttr(fileIDPtr, clientID, attrPtr)
  810.     Fs_FileID            *fileIDPtr;    /* FileID of pipe */
  811.     int             clientID;    /* IGNORED */
  812.     register Fs_Attributes    *attrPtr;    /* Attributes to update */
  813. {
  814.     Fsio_PipeIOHandle *handlePtr;
  815.  
  816.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, fileIDPtr);
  817.     if (handlePtr != (Fsio_PipeIOHandle *)NIL) {
  818.     attrPtr->serverID    = fileIDPtr->serverID;
  819.     attrPtr->domain        = fileIDPtr->major;
  820.     attrPtr->fileNumber    = fileIDPtr->minor;
  821.     attrPtr->type        = FS_LOCAL_PIPE;
  822.     attrPtr->size        = handlePtr->lastByte - handlePtr->firstByte +1;
  823.     attrPtr->devServerID    = fileIDPtr->serverID;
  824.     Fsutil_HandleRelease(handlePtr, TRUE);
  825.     }
  826.     return(SUCCESS);
  827. }
  828.  
  829. /*
  830.  *----------------------------------------------------------------------
  831.  *
  832.  * Fsio_PipeSetIOAttr --
  833.  *
  834.  *    Set the I/O attributes for a pipe.  This doesn't do anything.
  835.  *
  836.  * Results:
  837.  *    SUCCESS
  838.  *
  839.  * Side effects:
  840.  *      Updates the first and last byte indexes of the handle.
  841.  *
  842.  *----------------------------------------------------------------------
  843.  */
  844. /*ARGSUSED*/
  845. ReturnStatus
  846. Fsio_PipeSetIOAttr(fileIDPtr, attrPtr, flags)
  847.     Fs_FileID        *fileIDPtr;    /* FileID of pipe */
  848.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  849.     int            flags;        /* What attrs to set */
  850. {
  851.     return(SUCCESS);
  852. }
  853.  
  854. /*
  855.  * ----------------------------------------------------------------------------
  856.  *
  857.  * Fsio_PipeMigClose --
  858.  *
  859.  *    Release a reference on a Pipe I/O handle.
  860.  *    
  861.  * Results:
  862.  *    SUCCESS.
  863.  *
  864.  * Side effects:
  865.  *    Release the I/O handle.
  866.  *
  867.  * ----------------------------------------------------------------------------
  868.  *
  869.  */
  870. /*ARGSUSED*/
  871. ReturnStatus
  872. Fsio_PipeMigClose(hdrPtr, flags)
  873.     Fs_HandleHeader *hdrPtr;    /* File being released */
  874.     int flags;            /* Use flags from the stream */
  875. {
  876.     panic("Fsio_PipeMigClose called\n");
  877.     Fsutil_HandleRelease(hdrPtr, FALSE);
  878.     return(SUCCESS);
  879. }
  880.  
  881. /*
  882.  * ----------------------------------------------------------------------------
  883.  *
  884.  * Fsio_PipeMigrate --
  885.  *
  886.  *    This takes care of transfering references from one client to the other.
  887.  *    A useful side-effect of this routine is    to properly set the type in
  888.  *    the ioFileID, either FSIO_LCL_PIPE_STREAM or FSIO_RMT_PIPE_STREAM.
  889.  *    In the latter case FsrmtPipeMigrate is called to do all the work.
  890.  *
  891.  * Results:
  892.  *    An error status if the I/O handle can't be set-up.
  893.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  894.  *    bit set, and *sizePtr and *dataPtr are set to reference Fsio_DeviceState.
  895.  *
  896.  * Side effects:
  897.  *    Sets the correct stream type on the ioFileID.
  898.  *    Shifts client references from the srcClient to the destClient.
  899.  *
  900.  * ----------------------------------------------------------------------------
  901.  *
  902.  */
  903. /*ARGSUSED*/
  904. ReturnStatus
  905. Fsio_PipeMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  906.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  907.     int        dstClientID;    /* ID of target client */
  908.     int        *flagsPtr;    /* In/Out Stream usage flags */
  909.     int        *offsetPtr;    /* Return - new stream offset (not needed) */
  910.     int        *sizePtr;    /* Return - sizeof(Fsio_DeviceState) */
  911.     Address    *dataPtr;    /* Return - pointer to Fsio_DeviceState */
  912. {
  913.     Fsio_PipeIOHandle            *handlePtr;
  914.     Boolean                closeSrcClient;
  915.  
  916.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  917.     /*
  918.      * The pipe was local, which is usually true, but is now remote.
  919.      */
  920.     migInfoPtr->ioFileID.type = FSIO_RMT_PIPE_STREAM;
  921.     return(FsrmtPipeMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  922.         sizePtr, dataPtr));
  923.     }
  924.     migInfoPtr->ioFileID.type = FSIO_LCL_PIPE_STREAM;
  925.     handlePtr = Fsio_PipeHandleInit(&migInfoPtr->ioFileID, TRUE);
  926.  
  927.     PIPE_MIG_1(migInfoPtr, dstClientID);
  928.     /*
  929.      * At the stream level, add the new client to the set of clients
  930.      * for the stream, and check for any cross-network stream sharing.
  931.      */
  932.     Fsio_StreamMigClient(migInfoPtr, dstClientID, (Fs_HandleHeader *)handlePtr,
  933.             &closeSrcClient);
  934. /* XXX The above is a reference to the remote guy we've got a handle for,
  935.  * since we're the server and have the ioHandle with the buffer.  I guess this
  936.  * means that closeSrcClient must be false?  Or maybe both things happen and
  937.  * this is used for unmigrating too?
  938.  */
  939.     PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr);
  940.  
  941.     /*
  942.      * Adjust use counts on the I/O handle to reflect any new sharing.
  943.      */
  944.     Fsio_MigrateUseCounts(migInfoPtr->flags, closeSrcClient, &handlePtr->use);
  945.     PIPE_MIG_3(handlePtr);
  946.  
  947.     /*
  948.      * Move the client at the I/O handle level.
  949.      */
  950. /* XXX Do I need to do something here? */
  951.     Fsio_MigrateClient(&handlePtr->clientList, migInfoPtr->srcClientID,
  952.             dstClientID, migInfoPtr->flags, closeSrcClient);
  953.  
  954. /* XXX So now put newish handle in recov table? */
  955.     *sizePtr = 0;
  956.     *dataPtr = (Address)NIL;
  957.     *flagsPtr = migInfoPtr->flags;
  958.     *offsetPtr = migInfoPtr->offset;
  959.     /*
  960.      * We don't need this reference on the I/O handle; there is no change.
  961.      */
  962.     Fsutil_HandleRelease(handlePtr, TRUE);
  963.     return(SUCCESS);
  964. }
  965.  
  966. /*
  967.  * ----------------------------------------------------------------------------
  968.  *
  969.  * Fsio_PipeMigOpen --
  970.  *
  971.  *    Complete setup of a FSIO_LCL_PIPE_STREAM after migration (back) to the
  972.  *    pipe I/O server.  Fsio_PipeMigrate has done the work of shifting use
  973.  *    counts at the stream and I/O handle level.  This routine has to
  974.  *    increment the low level reference count on the pipe I/O handle
  975.  *    to reflect the existence of a new stream to the I/O handle.
  976.  *
  977.  * Results:
  978.  *    None.
  979.  *
  980.  * Side effects:
  981.  *    None.
  982.  *
  983.  * ----------------------------------------------------------------------------
  984.  *
  985.  */
  986. /*ARGSUSED*/
  987. ReturnStatus
  988. Fsio_PipeMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  989.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  990.     int        size;        /* Zero */
  991.     ClientData    data;        /* NIL */
  992.     Fs_HandleHeader **hdrPtrPtr;    /* Return - handle for the file */
  993. {
  994.     register Fsio_PipeIOHandle *handlePtr;
  995.  
  996.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, &migInfoPtr->ioFileID);
  997.     if (handlePtr == (Fsio_PipeIOHandle *)NIL) {
  998.     panic( "Fsio_PipeMigOpen, no handle\n");
  999.     return(FAILURE);
  1000.     } else {
  1001.     PIPE_MIG_END(handlePtr);
  1002.     Fsutil_HandleUnlock(handlePtr);
  1003.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  1004.     return(SUCCESS);
  1005.     }
  1006. }
  1007.  
  1008. /*
  1009.  *----------------------------------------------------------------------
  1010.  *
  1011.  * Fsio_PipeReopen --
  1012.  *
  1013.  *    Reopen a pipe for a client.  This executed on a server and will
  1014.  *    only work if it was a network partition that made us forget
  1015.  *    about the client.  If we've already removed the pipe handle
  1016.  *    then the clien't won't be able to recover.
  1017.  *
  1018.  * Results:
  1019.  *    A  non-SUCCESS return code if the re-open failed.
  1020.  *
  1021.  * Side effects:
  1022.  *    Adds the client to the set of client's for the pipe.
  1023.  *
  1024.  *----------------------------------------------------------------------
  1025.  */
  1026. /*ARGSUSED*/
  1027. ReturnStatus
  1028. Fsio_PipeReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  1029.     Fs_HandleHeader    *hdrPtr;        /* NIL */
  1030.     int            clientID;        /* Host ID of client */
  1031.     ClientData        inData;            /* sizeof Fsio_PipeReopenParams */
  1032.     int            *outSizePtr;        /* Returns 0 */
  1033.     ClientData        *outDataPtr;        /* Returns NIL */
  1034. {
  1035.     register Fsio_PipeIOHandle    *handlePtr;
  1036.     ReturnStatus        status;
  1037.     Fsio_PipeReopenParams        *reopenParamsPtr;
  1038.  
  1039.     reopenParamsPtr = (Fsio_PipeReopenParams *)inData;
  1040.     *outSizePtr = 0;
  1041.     *outDataPtr = (ClientData)NIL;
  1042.  
  1043.     /*
  1044.      * Old clients may still do reopens of pipes with no references (at least,
  1045.      * they do this with devices with no references), so protect ourselves
  1046.      * here on the server.  But since we don't recover pipes except after
  1047.      * network partitions, this may not be necessary.
  1048.      */
  1049.     if (reopenParamsPtr->use.ref == 0) {
  1050.     return SUCCESS;
  1051.     }
  1052.  
  1053.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, &reopenParamsPtr->fileID);
  1054.     if (handlePtr == (Fsio_PipeIOHandle *)NIL) {
  1055.     status = FAILURE;
  1056.     } else {
  1057.     Fsconsist_IOClientStatus(&handlePtr->clientList, clientID,
  1058.                  &reopenParamsPtr->use);
  1059.     (void)Fsconsist_IOClientReopen(&handlePtr->clientList, clientID,
  1060.                  &reopenParamsPtr->use);
  1061.     handlePtr->use.ref += reopenParamsPtr->use.ref;
  1062.     handlePtr->use.write += reopenParamsPtr->use.write;
  1063.     Fsutil_HandleRelease(handlePtr, TRUE);
  1064.     status = SUCCESS;
  1065.     }
  1066.     return(status);
  1067. }
  1068.  
  1069. /*
  1070.  *----------------------------------------------------------------------
  1071.  *
  1072.  * Fsio_PipeClientKill --
  1073.  *
  1074.  *    Clean up after a crashed client.  Note, this doesn't handle the
  1075.  *    obscure case of one end of a pipe being duplicated and then
  1076.  *    one of the sharers migrating to a host which crashes.  In this
  1077.  *    funny case we'll wrongly think that all users of one end of
  1078.  *    the pipe have crashed.
  1079.  *
  1080.  * Results:
  1081.  *      SUCCESS.
  1082.  *
  1083.  * Side effects:
  1084.  *      Removes the client (if applicable) from the pipe's set of clients.
  1085.  *    This will cause a FS_BROKEN_PIPE error unless the pipe is re-opened,
  1086.  *    which might happen in a network partition.  This unlocks the handle.
  1087.  *
  1088.  *----------------------------------------------------------------------
  1089.  */
  1090. void
  1091. Fsio_PipeClientKill(hdrPtr, clientID)
  1092.     Fs_HandleHeader *hdrPtr;     /* Handle to clean up */
  1093.     int clientID;        /* Host assumed down */
  1094. {
  1095.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  1096.     int refs, writes, execs;
  1097.     register ReturnStatus status;
  1098.  
  1099.     Fsconsist_IOClientKill(&handlePtr->clientList, clientID, &refs, &writes, &execs);
  1100.     status = PipeCloseInt(handlePtr, refs, writes, FALSE);
  1101.     if (status != FS_FILE_REMOVED) {
  1102.     Fsutil_HandleUnlock(handlePtr);
  1103.     }
  1104. }
  1105.  
  1106.  
  1107. /*
  1108.  *----------------------------------------------------------------------
  1109.  *
  1110.  * Fsio_PipeScavenge --
  1111.  *
  1112.  *    Scavenge a pipe.  The handle might be usless if all its
  1113.  *    client's have crashed.
  1114.  *
  1115.  * Results:
  1116.  *      TRUE if the handle was removed.
  1117.  *
  1118.  * Side effects:
  1119.  *      Unlocks the pipe's handle.
  1120.  *
  1121.  *----------------------------------------------------------------------
  1122.  */
  1123. Boolean
  1124. Fsio_PipeScavenge(hdrPtr)
  1125.     Fs_HandleHeader *hdrPtr;     /* Handle about to be deleted */
  1126. {
  1127. #ifdef notdef
  1128.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  1129.     if (List_IsEmpty(&handlePtr->clientList) &&
  1130.     (handlePtr->flags == (FSIO_PIPE_WRITER_GONE|FSIO_PIPE_READER_GONE))) {
  1131.     /*
  1132.      * Never scavenge pipe handles.  Regular recovery cleanup
  1133.      * should invoke the pipe close routines and do proper cleanup.
  1134.      */
  1135.     free(handlePtr->buffer);
  1136.     Fsutil_WaitListDelete(&handlePtr->readWaitList);
  1137.     Fsutil_WaitListDelete(&handlePtr->writeWaitList);
  1138.     Fsutil_HandleRemove(hdrPtr);
  1139.     fs_Stats.object.pipes--;
  1140.     return(TRUE);
  1141.     }
  1142. #endif notdef
  1143.     Fsutil_HandleUnlock(hdrPtr);
  1144.     return(FALSE);
  1145. }
  1146.  
  1147.  
  1148. /*
  1149.  *----------------------------------------------------------------------
  1150.  *
  1151.  * Fsio_PipeRecovTestUseCount --
  1152.  *
  1153.  *    For recovery testing, return the use count on the io handle.
  1154.  *
  1155.  * Results:
  1156.  *      The use count.
  1157.  *
  1158.  * Side effects:
  1159.  *      None.
  1160.  *
  1161.  *----------------------------------------------------------------------
  1162.  */
  1163. int
  1164. Fsio_PipeRecovTestUseCount(handlePtr)
  1165.     Fsio_PipeIOHandle *handlePtr;
  1166. {
  1167.     return handlePtr->use.ref;
  1168. }
  1169.  
  1170.  
  1171. /*
  1172.  *----------------------------------------------------------------------
  1173.  *
  1174.  * Fsio_PipeSetupHandle --
  1175.  *
  1176.  *    Given a pipe recovery object, setup the necessary handle state for it.
  1177.  *
  1178.  * Results:
  1179.  *    None.
  1180.  *
  1181.  * Side effects:
  1182.  *    A handle is created in put in the handle table.
  1183.  *
  1184.  *----------------------------------------------------------------------
  1185.  */
  1186. ReturnStatus
  1187. Fsio_PipeSetupHandle(recovInfoPtr)
  1188.     Fsrecov_HandleState    *recovInfoPtr;
  1189. {
  1190.     Fs_FileID        fileID;
  1191.     int            clientID;
  1192.     Fsio_PipeIOHandle    *handlePtr;
  1193.  
  1194.     if (!recov_Transparent) {
  1195.     panic("Fsio_PipeSetupHandle: shouldn't have been called.");
  1196.     }
  1197.     fileID = recovInfoPtr->fileID;
  1198.     clientID = fileID.serverID;
  1199.     fileID.serverID = rpc_SpriteID;
  1200.  
  1201.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, &fileID);
  1202.     if (handlePtr == (Fsio_PipeIOHandle *) NIL) {
  1203.     return FAILURE;
  1204.     }
  1205.     (void)Fsconsist_IOClientReopen(&handlePtr->clientList, clientID,
  1206.         &recovInfoPtr->use);
  1207.     handlePtr->use.ref += recovInfoPtr->use.ref;
  1208.     handlePtr->use.write += recovInfoPtr->use.write;
  1209.     Fsutil_HandleRelease(handlePtr, TRUE);
  1210.  
  1211.     return SUCCESS;
  1212. }
  1213.